/**
 * Class: ssi.peeno.managers.ConfigManager
 * 
 * Class to handle the configuration file. It allows to load config data
 * and then to access them in a static way.
 */

package ssi.peeno.managers;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class ConfigManager {
	private static XPath xpath;
	private static Document xmlDoc;
	private static boolean debug;
	private static String version;
	private static int port;
	private static String codename;
	private static String dbType;
	private static String dbName;
	private static String dbAddress;
	private static int dbPort;
	private static String dbUsername;
	private static String dbPassword;
	private static String keysDir;
	private static String keyPassword;
	private static boolean loaded = false;
	private static String privateKey;
	private static String publicKey;
	
	    
	public static void load(String configFilePath) {
		if (!loaded) {
			DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
	        DocumentBuilder db;
	        File xmlConfigFile = new File(configFilePath);
			try {
				db = bf.newDocumentBuilder();
				xmlDoc = db.parse(xmlConfigFile);			
			} catch (ParserConfigurationException e) {
				System.out.println("ERROR: Configuration file is invalid.");
				System.exit(1);
			} catch (SAXException e) {
				System.out.println("ERROR: Unable to parse the xml file.");
				System.exit(1);		
			} catch (IOException e) {
				System.out.println("ERROR: Configuration file doesn't exsist.");
				System.exit(1);
			}
	        XPathFactory xf = XPathFactory.newInstance();
	        xpath = xf.newXPath();
	        try {
				Node nd = (Node)xpath.evaluate("PeenoConfig", xmlDoc, XPathConstants.NODE);
				loadPeenoConf(nd);
				NodeList nl = (NodeList)xpath.evaluate("/PeenoConfig/database", xmlDoc, XPathConstants.NODESET);
				loadDatabaseConf(nl);
				nd = (Node)xpath.evaluate("PeenoConfig/keystorage", xmlDoc, XPathConstants.NODE);
				loadKeyStorageConf(nd);
			} catch (XPathExpressionException e) {
				System.out.println("ERROR: An error occurred while parsing the configuration file: " + e.getMessage());
				System.exit(1);			
			}
			loaded = true;
		}
	}
	
	public static String getCodename() {
		return codename;
	}

	public static String getDbType() {
		return dbType;
	}

	public static String getDbName() {
		return dbName;
	}

	public static String getDbAddress() {
		return dbAddress;
	}

	public static int getDbPort() {
		return dbPort;
	}

	public static String getDbUsername() {
		return dbUsername;
	}

	public static String getDbPassword() {
		return dbPassword;
	}

	public static int getPort() {
		return port;
	}

	public static String getVersion() {
		return version;
	}
	
	public static String getKeysDir() {
		return keysDir;
	}
	
	public static String getKeyPassword() {
		return keyPassword;
	}

	public static String getPrivateKey() {
		return privateKey;
	}

	public static String getPublicKey() {
		return publicKey;
	}
	
	private static void loadPeenoConf(Node nd) {
		version = (nd.getAttributes().getNamedItem("version").getTextContent());
		port = (Integer.parseInt(nd.getAttributes().getNamedItem("port").getTextContent()));
		codename = nd.getAttributes().getNamedItem("codename").getTextContent();
		privateKey = nd.getAttributes().getNamedItem("privateKey").getTextContent();
		publicKey = nd.getAttributes().getNamedItem("publicKey").getTextContent();
		debug = nd.getAttributes().getNamedItem("debug").getTextContent().equals("true") ? true : false;
	}
	
	private static void loadDatabaseConf(NodeList nl) throws DOMException, XPathExpressionException {
		dbName = nl.item(0).getAttributes().getNamedItem("name").getTextContent();
		dbType = nl.item(0).getAttributes().getNamedItem("type").getTextContent();
		dbAddress = ((Node)xpath.evaluate("host", nl.item(0), XPathConstants.NODE)).getTextContent();
		dbPort = Integer.parseInt(((Node)xpath.evaluate("port", nl.item(0), XPathConstants.NODE)).getTextContent());
		dbUsername = ((Node)xpath.evaluate("username", nl.item(0), XPathConstants.NODE)).getTextContent();
		dbPassword = ((Node)xpath.evaluate("password", nl.item(0), XPathConstants.NODE)).getTextContent();
	}
	
	private static void loadKeyStorageConf(Node nd) {
		keysDir = (nd.getAttributes().getNamedItem("dir").getTextContent());
		keyPassword = (nd.getAttributes().getNamedItem("password").getTextContent());
	}

	public static void log(String msg) {
		if (debug)
			System.out.println("[" + new Date().getTime() + "] " + msg);
	}
}
